package com.ruoyi.web.cp.service.merge;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.StrUtil;
import com.google.common.collect.HashBasedTable;
import com.google.common.collect.Multimap;
import com.google.common.collect.Table;
import com.ruoyi.web.core.config.ConfigLoader;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.nio.file.FileSystems;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

@Slf4j
@Service
public class NoMatchGameService {
    @Autowired
    private ConfigLoader configLoader;

    public void noMatchGames(String noMatchFileName, String sourceFileName, String targetFileName) {
        List<String> noMatchGames = FileUtil.readLines(configLoader.getRmPath() + "merge" + FileSystems.getDefault().getSeparator() + noMatchFileName + ".txt", "utf-8");
        List<String> games = FileUtil.readLines(configLoader.getRmPath() + sourceFileName + ".txt", "utf-8");
        List<String> matchGames = FileUtil.readLines(configLoader.getGamenamesPath() + targetFileName + ".txt", "utf-8");
        if (CollUtil.isEmpty(noMatchGames)) {
            return;
        }
        List<String> matchs = new ArrayList<>();
        String text = "{}={}";
        //遍历obGames，然后按\t分割，按第3个元素分类，再取第4个和第5个元素组成一个map

        //新建一个可以存储多个不同key的map
        Table<String, String, String> tableAB = HashBasedTable.create();
        Table<String, String, String> tableBA = HashBasedTable.create();
        games.stream().map(s -> s.split("\t")).forEach(s -> {
            String key = s[2].substring(0, 16);
            tableAB.put(key, s[3], s[4]);
            tableBA.put(key, s[4], s[3]);
        });
        Iterator<String> iterator = noMatchGames.iterator();
        while (iterator.hasNext()) {
            String game = iterator.next();
            String[] split = game.split("\t");
            String key = split[0].substring(0, 16).replace("23:59", "00:00");
            String teamA = split[2];
            String teamB = split[3];
            boolean flag = false;
            if (tableAB.row(key).containsKey(teamA)) {
                String tableB = tableAB.row(key).get(teamA);
                String matchGame = StrUtil.format(text, tableB, teamB);
                if (!matchGames.contains(matchGame) && !StrUtil.equals(tableB, teamB)) {
                    log.info("teamA:{},obTeamB:{},hcTeamB:{}", teamA, tableB, teamB);
                    matchs.add(matchGame);
                    flag = true;
                }
            }
            if (tableBA.row(key).containsKey(teamB)) {
                String tableA = tableBA.row(key).get(teamB);
                String matchGame = StrUtil.format(text, tableA, teamA);
                if (!matchGames.contains(matchGame) && !StrUtil.equals(tableA, teamA)) {
                    log.info("teamB:{},obTeamA:{},hcTeamA:{}", teamB, tableA, teamA);
                    matchs.add(matchGame);
                    flag = true;
                }
            }
            if (flag) {
                iterator.remove();
            }
        }
        iterator = noMatchGames.iterator();
        while (iterator.hasNext()) {
            String game = iterator.next();
            String[] split = game.split("\t");
            String key = split[0].substring(0, 16).replace("23:59", "00:00");
            String teamA = split[2];
            String teamB = split[3];

            Map<String, String> rowAB = tableAB.row(key);
            rowAB.keySet().forEach(rowA -> {
                String rowB = rowAB.get(rowA);
                if (similarityPercentage(rowA, teamA) >= 60 && similarityPercentage(rowB, teamB) >= 60) {
                    String matchGameA = StrUtil.format(text, rowA, teamA);
                    String matchGameB = StrUtil.format(text, rowB, teamB);
                    if (!matchGames.contains(matchGameA) && !rowA.equals(teamA)) {
                        log.info("obTeamA:{},hcTeamA:{}", rowA, teamA);
                        matchs.add(matchGameA);
                    }
                    if (!matchGames.contains(matchGameB) && !rowB.equals(teamB)) {
                        log.info("obTeamB:{},hcTeamB:{}", rowB, teamB);
                        matchs.add(matchGameB);
                    }
                }
            });
        }
        FileUtil.writeLines(matchs, configLoader.getGamenamesPath() + targetFileName + ".txt", "utf-8", true);
    }

    // 计算编辑距离
    public static int levenshteinDistance(String s1, String s2) {
        int[][] dp = new int[s1.length() + 1][s2.length() + 1];
        for (int i = 0; i <= s1.length(); i++) dp[i][0] = i;
        for (int j = 0; j <= s2.length(); j++) dp[0][j] = j;

        for (int i = 1; i <= s1.length(); i++) {
            for (int j = 1; j <= s2.length(); j++) {
                int cost = (s1.charAt(i - 1) == s2.charAt(j - 1)) ? 0 : 1;
                dp[i][j] = Math.min(
                        Math.min(dp[i - 1][j] + 1, dp[i][j - 1] + 1),
                        dp[i - 1][j - 1] + cost
                );
            }
        }
        return dp[s1.length()][s2.length()];
    }

    // 转换为百分比相似度
    public static double similarityPercentage(String s1, String s2) {
        int distance = levenshteinDistance(s1, s2);
        int maxLength = Math.max(s1.length(), s2.length());
        if (maxLength == 0) return 100.0; // 两个空字符串
        return (1.0 - ((double) distance) / maxLength) * 100.0;
    }
}
